package view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

import agents.resources.DriverUpdatePoints;

import view.panels.EastPanel;
import view.panels.MapPanel;
import view.panels.NorthPanel;

import model.LocalMessage;
import model.Model.Individuals;
import model.mapping.MapPoint;

import controller.Controller;

public class MainGUI extends JFrame implements Observer{

	//private MapImagePanel mapa;
	private MapPanel mapa;
	private JLabel newMap; 
	private NorthPanel panelSuperior;
	private EastPanel panelDerecha;
	private Controller controlador;
	//private KeyboardFocusManager manager;
	//private KeyDispacher keyDispacher;
	
	public MainGUI(Controller control,String nombre) {
		
		super(nombre);
		setLayout(new BorderLayout());
		controlador = control;
		newMap = new JLabel();
		mapa = new MapPanel(); // just a JPanel extension, add to any swing/awt container
		mapa.setZoom(16); // set some zoom level (1-18 are valid)
		double lon = -3.7322858;
		double lat = 40.4494742;
		Point position = mapa.computePosition(new Point2D.Double(lon,lat));
		mapa.setCenterPosition(position);
		mapa.repaint();
		mapa.getOverlayPanel().setVisible(false);
		panelSuperior = new NorthPanel(controlador,mapa);
		panelDerecha = new EastPanel(controlador);
		add(BorderLayout.NORTH,panelSuperior);	
		add(BorderLayout.EAST,panelDerecha);
		add(BorderLayout.CENTER,mapa);
	    controlador.getModel().addObserver(this);
	    controlador.setMap(mapa);
	    setResizable(false);
	    setSize(1000,700);
		setVisible(true);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
	}

	public void update(Observable o, Object arg) {
	
		LocalMessage mensaje = (LocalMessage)arg;
		Point posicion = null;
		Integer eleccion = null;
		switch(mensaje.getId()) {
			case 1: // Cambia el panel por la imagen al simular
				BufferedImage imagen = (BufferedImage)mensaje.getContent();
				remove(mapa);
				ImageIcon icon = new ImageIcon(imagen);
				newMap = new JLabel(icon);
				add(BorderLayout.CENTER,newMap);
				break;
			case 2: //Cambia la imagen por el panel al finalizar
				remove(newMap);
				add(BorderLayout.CENTER,mapa);
				break;
			case 3:
				panelSuperior.getPanelSimulacion().setEntornoConfigurado(true);
				break;
			case 4:
				Integer value = (Integer)mensaje.getContent();
				panelDerecha.getSpeed().setValue(value.intValue());
				break;
			case 5:
				posicion = (Point)mensaje.getContent();
				eleccion = JOptionPane.showConfirmDialog(getParent(),"Confirme que desea incluir este grupo de individuos ya excluidos.","Problema en la configuracion",JOptionPane.YES_NO_OPTION,JOptionPane.INFORMATION_MESSAGE);
				if (eleccion == JOptionPane.YES_OPTION) {
					controlador.eraseType(posicion.x);
					JOptionPane.showMessageDialog(getParent(),"Los individuos con las caracteristicas indicadas han sido incluidos.","Problema en la configuracion",JOptionPane.INFORMATION_MESSAGE);
				}
				else {
					controlador.eraseType(posicion.y);
					controlador.getModel().getIndividualsBuilder().setKey(controlador.getModel().getIndividualsBuilder().getKey()-1);
					JOptionPane.showMessageDialog(getParent(),"Los individuos con las caracteristicas indicadas permanecen excluidos.","Problema en la configuracion",JOptionPane.INFORMATION_MESSAGE);
				}
				break;
			case 6:
				JOptionPane.showMessageDialog(this,"El tipo de individuos introducido ya ha sido excluido.","Problema en la configuracion",JOptionPane.INFORMATION_MESSAGE);
				break;
			case 7:
				posicion = (Point)mensaje.getContent();
				eleccion = JOptionPane.showConfirmDialog(getParent(),"Confirme que desea excluir este grupo de individuos ya incluidos.","Problema en la configuracion",JOptionPane.YES_NO_OPTION,JOptionPane.INFORMATION_MESSAGE);
				if (eleccion == JOptionPane.YES_OPTION) {
					controlador.eraseType(posicion.x);
					JOptionPane.showMessageDialog(getParent(),"Los individuos con las caracteristicas indicadas han sido excluidos.","Problema en la configuracion",JOptionPane.INFORMATION_MESSAGE);
				}
				else {
					controlador.eraseType(posicion.y);
					controlador.getModel().getIndividualsBuilder().setKey(controlador.getModel().getIndividualsBuilder().getKey()-1);
					JOptionPane.showMessageDialog(getParent(),"Los individuos con las caracteristicas indicadas permanecen incluidos.","Problema en la configuracion",JOptionPane.INFORMATION_MESSAGE);
				}
				break;
			case 9:
				panelSuperior.getPanelSimulacion().setConfig(false);
				break;
			case 10:
				JOptionPane.showMessageDialog(getParent(),"No se pudo realizar la modificacion" +
						" debido a que ya hay un perfil del mismo tipo creado.","Problema al modificar",
						JOptionPane.INFORMATION_MESSAGE);
				break;
			case 11:
				updateImage((DriverUpdatePoints) mensaje.getContent());
				break;
		}
	}
	
	public void updateImage(DriverUpdatePoints points) {
		
		ArrayList<MapPoint> occuped = points.getOccupedPoints();
		ArrayList<MapPoint> free = points.getFreePoints();
		BufferedImage image = controlador.getModel().getMapImageBuilder().getStore().getMapImage();
		BufferedImage blackBoard = controlador.getModel().getMapImageBuilder().getStore().getBlackboardImage();
		while (!free.isEmpty()) {
			MapPoint point = free.remove(0);
			for (int k=point.x-1;k<=point.x+1;k++)
				for (int l=point.y-1;l<=point.y+1;l++)
					if (controlador.getModel().getMapCheckouts().isInMap(k,l))
						image.setRGB(k,l,blackBoard.getRGB(k,l));
		} 
		if (!occuped.isEmpty()) {
			MapPoint point = occuped.get(0);
			for (int k=point.x-1;k<=point.x+1;k++)
				for (int l=point.y-1;l<=point.y+1;l++)
					if (controlador.getModel().getMapCheckouts().isInMap(k,l))
						image.setRGB(k,l,Color.magenta.getRGB());
		}
		repaint();
	}
}
